package linz

/**
 * 函数简化写法
 * add == add2
 */
fun add(num1: Int, num2: Int): Int = num1 + num2

fun add2(num1: Int, num2: Int): Int {
    return num2 + num1
}

fun main() {
//    method()
//    method("林敏",35)
//
//    //不按参数传递顺序
//    login(age = 33, code = "23457", password = "123456", name = "好呀")

    //TODO 匿名函数学习
    anonymousMethod()

    //TODO 函数类型&隐式返回
//    第一步： 函数输入输出声明
    val methodAction :()-> String

    //第二步： 函数实现
    methodAction = {
        val value = 999
        "$value return"
        // 匿名函数不要写return，最后一行就是返回值
//        88
    }
    //第三步： 调用
    println(methodAction)

    //第四步：一步到位
    val methodAction2 :(Int, Int) -> String = { number1, number2->
        val inputValue = 999
        "$inputValue 参数 num1 $number1, num2 $number2"
    }

    println(methodAction2(1,2))

    //单一参数，默认命名
    val  methodActionIt:(String) -> String = {"$it input value"}
    println(methodActionIt("it"))

    //第五步： 再简化
    val method1 = {v1:Double,v2:Float, v3:Int ->
        "v1:$v1, v2:$v2 , v3: $v3"
    }
    println(method1(35.6, 55555.6F,1))


    //当返回值不同类型时，用any代替及Java中的Object
    val anyMethod = {num:Int ->
        when(num){
            1->"星期一"
            2->"星期二"
            else -> {
                -1
            }
        }
    }

    println(anyMethod(5))

//    var method: (Int) -> Unit = { println("output $it") }
    var method: (Int) -> Unit = { println("output $it") }
    method(888)
    var method01 = {it:Int -> println("output $it")}
    method01(999)
    method01.invoke(1000)

    // String.()  给String类，增加一个匿名函数 == 效果： 我们的 lambda体会持有String本身 == this
    //匿名函数lambda 写法
    var anonymousMeothd : String.() -> Unit = {
        // this == String
        println("你是$this")
    }

    "Hello Kotlin".anonymousMeothd()

    var intLambdaMethod : Int.(Int) -> String = {"this: ${this}  it:{$it}"}
    //todo 三种调用的方法
    println(12.intLambdaMethod(666))
    println(intLambdaMethod(777, 888))
    println(intLambdaMethod.invoke(9999, 1000))

    //todo method 返回值需要return，不像lambda一样默认最后一行为返回值
    fun t01(){123131213.45F} // 打印 kotlin.Unit
    fun t02(){true} // 打印 kotlin.Unit
    fun t03():String{ return "Hello Word"}

    fun s01() /*: () -> Unit*/ = {} // () -> Unit
    fun s02() /*: () -> Unit*/ = { println("OK") }  // () -> Unit
    println(t02())

    // run { 执行你的函数 show1 show2  }
    fun s03() : Boolean = run { true } // Boolean    run返回 {}里面的函数返回类型
    fun s04() : ()-> Boolean = { true } // () -> Boolean    输入 -> 输出

    println(s04()) // () -> kotlin.Boolean
    println(s04()()) // true

    // (Int)->Unit
    fun k01() /*: (Int)->Unit*/ = {n1: Int -> println("你的输入类型是int? ${if (n1 is Int) "你是Int类型:$n1" else "你不是Int"}")}
    k01()(88) // (88) 执行 你函数返回的函数

    // (Int,Int) -> Char
    fun k02() : (Int,Int) -> Char = {n1: Int, n2: Int -> println("两数相加:${n1 + n2}")
        true
        'A'
    } // 划重点，想写多行直接敲回车，为什么要换行：为了编译器检查

    // fun aa{} 与 var aa={}有啥区别
    fun aa() {}
    var aa2 = {}
    // aa就是一个函数，实打实的函数
    // aa2 是接收一个匿名函数的变量而已，这个变量 可以执行这个匿名函数
    // 共同点：他们现象是一样的
    var aa3 = aa2 // 都属于函数引用的概念
    var aa4 = ::aa // 实打实的函数 变成 函数引用 所以可以传递赋值 给另外一个变量
}

fun anonymousMethod(){
   val len =  "Linzhi".count();
    println(len)
    val len2 = "Linzhi".count {
        it == 'i'
    }
    println(len2)
}

/**
 * 默认值 方法
 */
fun method(name: String = "林", age: Int = 33) {
    println("你的名字${name} , 客户年龄 $age")
}


/**
 * 拒名参数，可以不按照参数传递顺序
 */
fun login(name: String, age: Int, password: String, code: String) {
    println("你的名字${name} , 客户年龄 $age code= $code  password=$password")
}


/**
 *  Java void 是关键字，不是类型
 * :Unit 不写，默认也有， Unit代表无参数返回,是一个类，我们可以做更多的操作
 */
private fun Void(): Unit {
}

private fun Void2() {
}

private fun Void3() {
    return println()
}

